package com.babasport.service.base;

import java.util.HashMap;
import java.util.LinkedHashMap;

import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.babasport.bean.QueryResult;

// 使用Spring提供的默认事务
@Transactional
public class DAOSupport implements DAO {

	@PersistenceContext
	protected EntityManager em;

	@Override
	public <T> void delete(Class<T> entityClass, Object entityID) {
		em.remove(em.getReference(entityClass, entityID));
	}

	@Override
	public <T> void delete(Class<T> entityClass, Object[] entityIDs) {
		for (Object object : entityIDs) {
			this.delete(entityClass, object);
		}
	}

	@Override
	// 查询操作不允许有数据更新行为, 且不需要事务
	@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
	public <T> T query(Class<T> entityClass, Object entityID) {
		return em.find(entityClass, entityID);
	}

	@Override
	public void save(Object entity) {
		em.persist(entity);
	}

	@Override
	public void update(Object entity) {
		em.merge(entity);
	}

	protected <T> String getEntityName(Class<T> entityClass) {
		String entityName = entityClass.getSimpleName();
		Entity entity = entityClass.getAnnotation(Entity.class);
		if (entity.name() != null && !"".equals(entity.name())) {
			entityName = entity.name();
		}
		return entityName;
	}

	@Override
	public <T> QueryResult<T> getScrollData(Class<T> entityClass) {
		return getScrollData(entityClass, -1, -1, null, null);
	}

	@Override
	public <T> QueryResult<T> getScrollData(Class<T> entityClass,
			int firstIndex, int maxIndex) {
		return getScrollData(entityClass, firstIndex, maxIndex, null, null);
	}

	@Override
	public <T> QueryResult<T> getScrollData(Class<T> entityClass,
			int firstIndex, int maxIndex, LinkedHashMap<String, String> orderBy) {
		return getScrollData(entityClass, firstIndex, maxIndex, null, orderBy);
	}

	@Override
	public <T> QueryResult<T> getScrollData(Class<T> entityClass,
			int firstIndex, int maxIndex, HashMap<String, Object> where) {
		return getScrollData(entityClass, firstIndex, maxIndex, where, null);
	}

	@Override
	@SuppressWarnings("unchecked")
	// 查询操作不允许有数据更新行为, 且不需要事务
	@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
	public <T> QueryResult<T> getScrollData(Class<T> entityClass,
			int firstIndex, int maxIndex, HashMap<String, Object> where,
			LinkedHashMap<String, String> orderBys) {

		String entityName = this.getEntityName(entityClass);
		Query query = em.createQuery("select o from " + entityName + " o "
				+ this.buildWhereSql(where) + this.buildOrderBySql(orderBys));
		if (firstIndex != -1 && maxIndex != -1) {
			query.setFirstResult(firstIndex).setMaxResults(maxIndex);
		}
		Query queryTR = em.createQuery("select count(o) from " + entityName
				+ " o");
		return new QueryResult<T>(query.getResultList(), (Long) queryTR
				.getSingleResult());
	}

	/**
	 * 组装where SQL语句
	 * 
	 * @param where
	 * @return
	 */
	private String buildWhereSql(HashMap<String, Object> where) {
		StringBuilder orderBySql = new StringBuilder("");
		if (where != null && where.size() > 0) {
			orderBySql.append(" where ");
			int idx = 0;
			for (String key : where.keySet()) {
				orderBySql.append(" o.").append(key).append(
						where.get(key));
				if (idx++ < where.size() - 1) {
					orderBySql.append(" and ");
				}
			}
		}
		return orderBySql.toString();
	}

	/**
	 * 组装order by SQL语句
	 * 
	 * @param orderBys
	 * @return
	 */
	private String buildOrderBySql(LinkedHashMap<String, String> orderBys) {
		if (orderBys != null && orderBys.size() > 0) {
			StringBuilder orderBySql = new StringBuilder("");
			orderBySql.append(" order by ");
			for (String key : orderBys.keySet()) {
				orderBySql.append(" o.").append(key).append(" ").append(
						orderBys.get(key)).append(",");
			}
			return orderBySql.deleteCharAt(orderBySql.length() - 1).toString();
		}
		return "";
	}

}
